library ieee;
use ieee.std_logic_1164.all;

-- This arbitrary state machine is probably not very useful in reality, but demonstrates 

entity table_emulator is
    port (clock               			: in  std_logic;
          reset               			: in  std_logic;
          TBL_to_FWD_ACK				: out std_logic;
	      TBL_to_FWD_Valid				: out std_logic;
	      TBL_to_FWD_Port				: out std_logic_vector(2 downto 0);
	      FWD_to_TBL_ACK				: in  std_logic;
	      FWD_to_TBL_desAddress			: in  std_logic_vector(47 downto 0);
	      FWD_to_TBL_srcPort			: in  std_logic_vector(1 downto 0);
	      FWD_to_TBL_srcAddress			: in  std_logic_vector(47 downto 0)
	   );
end table_emulator;

architecture behavior of table_emulator is

type   state_type is (wait_state, pause_state, ack_state, response_state);
signal my_state_reg, my_state_next: state_type:= wait_state;
signal stored_addr	: std_logic_vector(47 downto 0);
signal ff_en 		: std_logic;

component addr_ff is
	port
	(
		aclr		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (47 DOWNTO 0);
		enable		: IN STD_LOGIC ;
		q			: OUT STD_LOGIC_VECTOR (47 DOWNTO 0)
	);
end component;

begin

-- Update state on rising edges or a reset
process(clock, reset)
	begin
		if(reset ='1') then 
		  my_state_reg <= wait_state;
		elsif(clock'event and clock='1') then
			my_state_reg<=my_state_next;
		end if;
	end process;

process(my_state_reg, FWD_to_TBL_ACK) 
	begin
	    case my_state_reg is
			when wait_state =>
				if FWD_TO_TBL_ACK='1' then
					my_state_next <= ack_state;
				else
					my_state_next <= wait_state;
				end if;
		    when pause_state =>
		        my_state_next <= response_state;
			when ack_state =>
				my_state_next <= pause_state;
			when response_state =>
				my_state_next <= wait_state;
		end case;
	end process;
	
process (my_state_reg,stored_addr)  -- Moore output logic
	begin
	    TBL_to_FWD_ACK <= '0';
	    TBL_to_FWD_Valid <= '0';
	    ff_en <= '0';
	    TBL_to_FWD_Port <= "000";
		case my_state_reg is
			when wait_state => ff_en <= '1';
			when pause_state =>
			when ack_state =>
			    TBL_to_FWD_ACK <= '1';
			when response_state => 
				TBL_to_FWD_Port <= stored_addr(2 downto 0);
				TBL_to_FWD_Valid <= '1';
		end case;
	end process;

ff: addr_ff port map(reset,clock,FWD_to_TBL_desAddress,ff_en,stored_addr);

end behavior;